package iit.projects.etaxi.model.dao;

import iit.projects.etaxi.model.dto.DriverSCDO;
import iit.projects.etaxi.model.entity.Driver;
import iit.projects.etaxi.model.entity.VehicleLocation;
import iit.projects.etaxi.model.exception.DriverNotFoundException;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public class HibernateDriverDao extends HibernateDaoSupport implements
		DriverDao {

	final Logger log = LoggerFactory.getLogger(HibernateDriverDao.class);
	
	@SuppressWarnings("unchecked")
	@Override
	public Driver findDriverByContactNumber(String contactNumber) throws DriverNotFoundException {
		if(log.isDebugEnabled()){
			log.debug("Going to find Driver by contact number " + contactNumber);
		}
		
		Session session = getSession(false);
		
		try{
			Criteria criteria = session.createCriteria(Driver.class);
			criteria.add(Restrictions.eq("contactNumber", contactNumber));
			
			List<Driver> list = criteria.list();
			if(list != null && !list.isEmpty()){
				return list.iterator().next();
			}
			else{
				throw new DriverNotFoundException();
			}
		}catch(HibernateException ex){
			throw convertHibernateAccessException(ex);
		}
	}
	
	@Override
	public Driver updateDriver(Driver driver){
		if(log.isDebugEnabled()){
			log.debug("Going to update Driver " + driver.getId());
		}
		
		Session session = getSession(false);
		try{
			return (Driver)session.merge(driver);
		}catch(HibernateException ex){
			throw convertHibernateAccessException(ex);
		}
	}
	
	@SuppressWarnings("unchecked")
	public List<Driver> findDrivers(DriverSCDO driverSCDO) {
		if(log.isDebugEnabled()){
			log.debug("Finding Drivers");
		}
		
		List<Driver> list = null;
		Session session = getSession(false);
		
		try {
			
			String code = driverSCDO.getCode();
			String name = driverSCDO.getName();
			String contactNumber = driverSCDO.getContactNumber();
			
			Criteria criteria = session.createCriteria(Driver.class);
			if (name != null && !name.isEmpty()) {
				if (!name.contains("%")) {
					name = "%" + name + "%";
				}
				criteria.add(Restrictions.like("name", name));
			}
			
			if (code != null && !code.isEmpty()) {
				if (!code.contains("%")) {
					code = "%" + code + "%";
				}
				criteria.add(Restrictions.like("code", code));
			}
			
			
			if (contactNumber != null && !contactNumber.isEmpty()) {
				if (!contactNumber.contains("%")) {
					contactNumber = "%" + contactNumber + "%";
				}
				criteria.add(Restrictions.like("contactNumber", contactNumber));
			}

			criteria.addOrder(Order.asc("code"));
			list = criteria.list();
		} catch (HibernateException ex) {
			throw convertHibernateAccessException(ex);
		}
		
		populateLastLocations(list);
		
		return list;
	}
	
	private void populateLastLocations(List<Driver> drivers){
		
		if(drivers == null || drivers.isEmpty()){
			return;
		}
		
		for(Driver driver : drivers){
			
			List<VehicleLocation> vehicleLocations = 
				new ArrayList<VehicleLocation>(driver.getVehicle().getVehicleLocations());
			
			Collections.sort(vehicleLocations);
			
			if(!vehicleLocations.isEmpty()){
				driver.setLastLocation((vehicleLocations.get(0)).getLocation().getName());
			}
		}
	}
}
